package sqlite

import (
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
	"gorm.io/gorm/logger"
	"os"
	"path/filepath"
	"sort"
	"stock/server/dao"
	"stock/server/internal/pkg/pathulit"
)

type Option struct {
	FilePath string
	gorm.Config
}

type Sqlite struct {
	db          *gorm.DB
	codeInfoMap map[string]dao.StockInfo
}

var _ dao.IStockDB = (*Sqlite)(nil)

func (o *Sqlite) Group() (groupIdx []string, resp map[string][]string) {
	// todo 后期支持自定义分组
	resp = make(map[string][]string)
	for code, info := range o.codeInfoMap {
		typ := info.Type
		switch info.Type {
		case "stock":
			typ = "个股"
		case "index":
			typ = "指数"
		}

		resp[typ] = append(resp[typ], code)
	}

	for groupName := range resp {
		groupIdx = append(groupIdx, groupName)
	}
	sort.Strings(groupIdx)

	return groupIdx, resp
}

func (o *Sqlite) Open(option any) (db dao.IStockDB, err error) {
	opt := option.(Option)

	if opt.FilePath != "" {
		if _, err := os.Stat(opt.FilePath); err != nil {
			panic(err)
		}
	} else {
		exePath, err := pathulit.ExePath()
		if err != nil {
			return nil, err
		}

		opt.FilePath = filepath.Join(exePath, opt.FilePath)
	}

	if opt.Config.Logger == nil {
		opt.Config.Logger = logger.Default.LogMode(logger.Info)
	}

	sqlDb, err := gorm.Open(sqlite.Open(opt.FilePath), &opt.Config)
	if err != nil {
		panic("failed to connect database")
	}

	o.db = sqlDb

	return o, nil
}

func (o *Sqlite) CodeInfo() map[string]dao.StockInfo {
	var rows []dao.StockInfo
	o.db.Table("stock_info").Select("exchange || code AS code, title, COALESCE(NULLIF(abbreviation, ''), title) AS abbreviation, trading_period, type").Find(&rows)

	o.codeInfoMap = make(map[string]dao.StockInfo)
	for _, row := range rows {
		o.codeInfoMap[row.Code] = row

	}

	return o.codeInfoMap
}
